package com.res.common.controller;

import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.SessionAttributes;

import com.res.simulator.handler.CommonFileHandler;
import com.res.simulator.handler.GenericAPIExecutionHandler;
import com.res.simulator.handler.APIInvocationHandler;
import com.res.simulator.model.GenericAPIExecutionModel;
import com.res.simulator.model.RestServiceModel;
import com.res.simulator.model.SavedAPIModel;
import com.res.simulator.model.SelectTemplateModel;
import com.res.simulator.view.ConsumerTemplateSaveView;
import com.res.simulator.view.ConsumerTemplateSearchResultsView;
import com.res.simulator.view.ResultView;
import com.res.system.common.SessionRegistry;
import com.res.system.referencedata.ReferenceDataManager;

@Controller
@SessionAttributes
public class GenericAPIExecutionPageController extends BaseController {

    private static final Logger logger = Logger.getLogger(GenericAPIExecutionPageController.class);

    private void init() {

        try {

            ReferenceDataManager.getInstance().load();

        } catch (Exception e) {

            e.printStackTrace();
        }

        if (null == getSession().getAttribute("systemCollection")) {

            final Map<String, String> systemMap = new HashMap<String, String>();

            List<Object[]> systemInfoList = new ArrayList<Object[]>();
            List<String> systemNameList = new ArrayList<String>();

            try {

                systemInfoList = ReferenceDataManager.getInstance().getSystemInfoList();
                systemNameList = ReferenceDataManager.getInstance().getSystemNameList();

            } catch (Exception e) {
                e.printStackTrace();
            }

            for (Object[] objectArray : systemInfoList) {
                logger.info("==system Info====>" + objectArray[0].toString() + "___" + objectArray[1].toString());
                systemMap.put(String.valueOf(objectArray[0]), objectArray[1].toString());

            }
            // ------------------logs----------------------------------------------------------------
            for (String key : systemMap.keySet()) {
                logger.info("==system Info=Key===>" + key);
                logger.info("==system Info=Value===>" + systemMap.get(key));
            }

            getSession().setAttribute("systemCollection", systemNameList);

            if (null == getSession().getAttribute("packageNameCollection")) {

                final Map<String, String> packageNameMap = new HashMap<String, String>();

                List<Object> packageHierachyList = new ArrayList<Object>();
                packageHierachyList = getPackageList(packageNameMap, packageHierachyList);

                // ------------------logs---------------------------------------------------------------
                for (String key : packageNameMap.keySet()) {
                    logger.info("==pakcage key===>" + key);
                    logger.info("==pakcage Value===>" + packageNameMap.get(key));
                }

                getSession().setAttribute("packageNameCollection", packageHierachyList);
            }
        }
    }

    @RequestMapping("/genericapiexecutionmainpage")
    public String home(@ModelAttribute("GenericAPIExecutionModel") final GenericAPIExecutionModel model, final BindingResult result) {

        init();

        return "genericapiexecutionlayout";
    }

    @RequestMapping(value = "/api_execution", method = RequestMethod.GET, params = {"systemName", "packageName"})
    protected String selectSystemName(@ModelAttribute("GenericAPIExecutionModel") final GenericAPIExecutionModel model, final BindingResult result)
        throws Exception {

        getSession().setAttribute("SystemName", model.getSystemName());

        return "redirect:genericapiexecutionmainpage.htm";
    }

    @RequestMapping(value = "/api_execution", method = RequestMethod.GET, params = {"systemName", "packageName", "apiName"})
    protected String search(@ModelAttribute("GenericAPIExecutionModel") final GenericAPIExecutionModel model, final BindingResult result)
        throws Exception {

        getSession().setAttribute("selectedPackageName", model.getPackageName());

        final GenericAPIExecutionHandler handler = new GenericAPIExecutionHandler();
        final List<ConsumerTemplateSearchResultsView> genericAPISearchResultsView = handler.process(model);

        getSession().setAttribute(SessionRegistry.GENERIC_API_SEARCH_RESULTS_VIEW, genericAPISearchResultsView);

        return "redirect:genericapiexecutionmainpage.htm";
    }

    /**
     * The method handle font end Ajax call.
     * 
     * @param model
     * @return
     */
    @RequestMapping(value = "/feed_hidden_data", method = RequestMethod.GET)
    public void feedHiddenData(@RequestParam("apiId") String apiId, @RequestParam("consumerString") String consumerString) {

        if (apiId.trim().length() != 0) {
            getSession().setAttribute(SessionRegistry.API_ID_HIDDEN_VARIABLE, apiId);
        }

        if (consumerString.trim().length() != 0) {
            getSession().setAttribute(SessionRegistry.CONSUMER_STRING_HIDDEN_VARIABLE, consumerString);
        }

    }
    
    /**
     * The method handle font end Ajax call.
     * 
     * @param model
     * @return
     */
    @RequestMapping(value = "/feed_query_param", method = RequestMethod.GET)
    public void feedQueryParamData(@RequestParam("apiId") String apiId, @RequestParam("urlParam") String queryParam) {

        Object object = getSession().getAttribute(SessionRegistry.PACKAGE_CHANGE_SETMAP_HIDDEN_VARIABLE);

        final Map<String, String> packageChangeSet = object == null ? new HashMap<String, String>() : (Map<String, String>) object;

        packageChangeSet.put(apiId, queryParam);
        getSession().setAttribute(SessionRegistry.PACKAGE_CHANGE_SETMAP_HIDDEN_VARIABLE, packageChangeSet);

    }

    /**
     * Method handle content selection of api popup window.
     * 
     * @param model
     * @param result
     * @param content
     * @return
     */
    @RequestMapping(value = "/genericapiexecutionmainpage", method = RequestMethod.GET, params = {"consumerContent"})
    public String consumerTemplateRowSelection(@ModelAttribute("GenericAPIExecutionModel") final GenericAPIExecutionModel model, final BindingResult result,
        @RequestParam("consumerContent") String content) {

        model.setConsumerString(content);

        return "genericapiexecutionlayout";
    }

    /**
     * The method will handle api invocation.
     * 
     * @param model GenericAPIExecutionModel
     * @param result Default spring BindingResult.
     * @return view string.
     * @throws Exception
     */
    @RequestMapping(value = "/api_execution", method = RequestMethod.GET, params = {"systemName", "packageName", "apiName", "Submit"})
    public String invokeAPI(@ModelAttribute("GenericAPIExecutionModel") final GenericAPIExecutionModel model, final BindingResult result)
        throws Exception {

        final APIInvocationHandler handler = new APIInvocationHandler();
        final String apiId = (String) getSession().getAttribute(SessionRegistry.API_ID_HIDDEN_VARIABLE);
        
        if(null != getSession().getAttribute(SessionRegistry.PACKAGE_CHANGE_SETMAP_HIDDEN_VARIABLE) && null != apiId){
            
            final Map<String, String> packageChangeSet = (Map<String, String>) getSession().getAttribute(SessionRegistry.PACKAGE_CHANGE_SETMAP_HIDDEN_VARIABLE);

            final String queryParam = packageChangeSet.get(apiId);
            
            model.setPackageName(queryParam);
                        
        }

        model.setApiId(apiId);
        final ResultView resultViewObj = handler.process(model);

        List<ResultView> resultViewList = new ArrayList<ResultView>();

        if (null != getSession().getAttribute(SessionRegistry.RESULT_VIEW)) {
            resultViewList = (List<ResultView>) getSession().getAttribute(SessionRegistry.RESULT_VIEW);
        }

        resultViewList.add(resultViewObj);
        getSession().setAttribute(SessionRegistry.RESULT_VIEW, resultViewList);

        return "genericapiexecutionlayout";

    }
    
    @RequestMapping(value = "/downloadResultXML", method = RequestMethod.GET)
    public String downloadResultFile(final HttpServletRequest request, HttpServletResponse response,@ModelAttribute("GenericAPIExecutionModel") final GenericAPIExecutionModel model, final BindingResult result) throws IOException {

    	List<ResultView> resultViewList = (List<ResultView>) getSession().getAttribute(
            SessionRegistry.RESULT_VIEW);
        
        final String id = (String) request.getParameter("RecordId");
        ResultView selectedResultView = null;
        
        for (final ResultView resultView : resultViewList) {

            if (id.trim().length() != 0 && null != resultView && null != resultView.getRecordId() && resultView.getRecordId().equals(Long.valueOf(id))) {
            	selectedResultView = resultView;
                break;
            }

        }
        
        if( null != selectedResultView) {
        
        logger.info("Record id>"+selectedResultView.getRecordId());
        
        response.setContentType("application/xml");
        response.addHeader("Content-disposition", "atachment; filename=APIExecution_Search_ApiName_" + selectedResultView.getApiName()+".txt");

        final OutputStream buffoutput = new BufferedOutputStream(response.getOutputStream());
        final OutputStreamWriter outputwriter = new OutputStreamWriter(buffoutput);
       

        final CommonFileHandler fileHandler = new CommonFileHandler();
        final StringBuilder stringBuilder = fileHandler.read(selectedResultView.getLocation());

        outputwriter.write(stringBuilder.toString());
        outputwriter.flush();
        outputwriter.close();
        
        }
        
        return "genericapiexecutionlayout";
        
        
    }
    

    private List<Object> getPackageList(final Map<String, String> packageNameMap, List<Object> packageHierachyList) {

        try {
            packageHierachyList = ReferenceDataManager.getInstance().getPackageHierachyList();
        } catch (Exception e) {

            e.printStackTrace();
        }
        for (Object packageHierachy : packageHierachyList) {
            packageNameMap.put((String) packageHierachy, packageHierachy.toString());
        }
        return packageHierachyList;
    }

}
